package zl.demo;

import java.awt.Graphics;
import java.io.File;
import java.text.DateFormat;
import java.util.Date;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;

//自定义窗口类继承JFrame类
public class ResourceManage extends JFrame
{

	private static final long serialVersionUID = 1L;
	private JSplitPane jsp;   //定义拆分面板
	private JScrollPane jspTable;   //定义表格所在的滚动面板
	private JScrollPane jspTree;    //定义树空间所在的滚动面板
	private JTree tree;     //定义树对象
	private JTable table;    //定义表对象
	private DefaultMutableTreeNode root;

	private Vector<String> names;
	private Vector<Vector> datas;

	/**
	 *构造函数。完成一些初始化、及窗口配置信息
	 */
	public ResourceManage()
	{
		this.setTitle("资源管理器");   //设置窗体标题
		this.setSize(800,600);     //设置窗体默认大小
		//设置窗体的默认关闭方式
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		//定位窗体至屏幕中央
		this.setLocation(
			//this.getToolkit().getScreenSize() 获取工作屏幕的大小
			this.getToolkit().getScreenSize().width / 2 - this.getWidth() / 2,
			this.getToolkit().getScreenSize().height / 2 - this.getHeight() / 2
		);
		
		//设置窗体内容面板布局方式、1行2列
		//this.getContentPane().setLayout(new GridLayout(1,2));
		
		//调用方法、实例化JTree对象
		this.instanceJTree();
		//调用方法、实例化JTable对象
		this.instanceJTable();
		//将树控件放在一个滚动面板里面
		this.jspTree = new JScrollPane(this.tree);
		//将表格控件放在一个滚动面板里面
		this.jspTable = new JScrollPane(this.table);
		//实例化拆分面板  并将两个滚动面板以左右拆分的方式放入拆分面板
		this.jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,this.jspTree,this.jspTable);   
		this.jsp.setDividerSize(3);    //设置拆分条的大小
		this.jsp.setDividerLocation(200);   //定位初始分割线
		this.add(this.jsp);        //将拆分面板添加到窗体
		this.setVisible(true);     //设置窗体显示
	}

	/**
	 *此方法实例化JTable表格、
	 */
	public void instanceJTable()
	{
		this.names = new Vector<String>();
		this.names.add("名称");
		this.names.add("修改日期");
		this.names.add("类型");
		this.names.add("大小");
		this.datas = new Vector<Vector>();
		this.table = new JTable(datas,names);
	}

	/**
	 *此方法实例化JTree树、并添加树根
	 */
	public void instanceJTree()
	{
		//实例化树根
		this.root = new DefaultMutableTreeNode("我的电脑");
		this.initial();  //初始化树
		this.tree = new JTree(this.root);   //根据根节点实例化树控件
		//注册事件
		/*this.tree.addTreeExpansionListener(new TreeExpansionListener(){
			//节点关闭时响应
			public void treeCollapsed(TreeExpansionEvent e){}
			//节点展开时响应
			public void treeExpanded(TreeExpansionEvent e){}
		});*/
		this.tree.addTreeSelectionListener(new TreeSelectionListener(){
			//节点被选中时响应
			public void valueChanged(TreeSelectionEvent e)
			{
				//根据事件源获得被选中的树枝
				DefaultMutableTreeNode d = (DefaultMutableTreeNode)(e.getPath().getLastPathComponent());
				//得到树枝里面保存的文件夹完整路径信息
				if(d==ResourceManage.this.root)
					return;      //如果单击的是树根、则无任何操作
				//得到树枝上保存的文件夹路径信息
				File file = ((Tag)(d.getUserObject())).getPath();
				if(null != file && null != file.listFiles())
				{
					ResourceManage.this.datas.clear();   //清空表格数据
					//循环遍历文件夹、将信息添加到表格
					for(File f : file.listFiles())
					{
						Vector<String> v = new Vector<String>();
						v.add(f.getName());     //保存文件夹或文件名称
						//保存文件最后修改路径
						v.add(DateFormat.getDateInstance().format(new Date(f.lastModified())).toString()); 
						//判断是文件还是文件夹
						if(f.isFile())
						{
							v.add(f.getName().substring(f.getName().lastIndexOf(".") + 1));
						}
						else
						{
							v.add("文件夹");
						}
						//保存文件或文件夹的大小
						v.add(String.valueOf(f.length())+" Byte");
						//将信息添加到表格
						ResourceManage.this.datas.add(v);
					}
				}
				ResourceManage.this.repaint();   //重绘窗口
			}
		});
		this.tree.addTreeWillExpandListener(new TreeWillExpandListener(){
			//节点将关闭时响应
			public void treeWillCollapse(TreeExpansionEvent e){}
			//节点将展开时响应
			public void treeWillExpand(TreeExpansionEvent e)
			{
				//根据事件源获得将被展开的树枝
				DefaultMutableTreeNode d = (DefaultMutableTreeNode)(e.getPath().getLastPathComponent());
				//得到树枝里面保存的文件夹完整路径信息
				if(d==ResourceManage.this.root)
					return;      //如果单击的是树根、则无任何操作
				File f = ((Tag)(d.getUserObject())).getPath();
				//调用方法给该树枝添加分枝
				ResourceManage.this.addChildren(d,f);
			}
		});
	}

	/**
	 *重写JFrame的paint方法
	 *此方法由系统调用、
	 *当调用repaint方法时系统自动调用此方法
	 */
	public void paint(Graphics g)
	{
		//覆盖paint方法
		this.remove(this.jsp);    //清空窗体
		this.add(this.jsp);        //将拆分面板添加到窗体
		super.paint(g);     //重绘窗体
	}

	
	/**
	 *初始化方法 用来读取硬盘的盘符并生成相应的树枝
	 */
	public void initial()
	{
		//listRoots()  获得所有存储介质的所有盘符
		for(File f : File.listRoots())
		{
			if(null != f.listFiles())  //判断盘符是否为空
			{
				//如果盘符不为空则实例化一个树枝。并保存完整的路径信息、
			    //完整路径由自定义的“Tag”类封装
				DefaultMutableTreeNode d = new DefaultMutableTreeNode(new Tag(f.getPath().replace(File.separator,""),f.getAbsoluteFile()));
				if(this.containerDirectory(f))
					d.add(new DefaultMutableTreeNode());
				//将盘符添加到树根
				this.root.add(d);
			}
		}
	}

	/**
	 *@param dmtn   需要添加分枝的树枝
	 *@param file   分枝所在的路径、须为文件夹
	 *此方法用来给指定的树枝添加分枝 一个分枝保存的是一个文件夹的完整路径
	 */
	public void addChildren(DefaultMutableTreeNode dmtn,File file)
	{
		//如果树枝为null或路径不为文件夹则结束方法
		if(null == dmtn || !file.isDirectory())
			return;
		//添加前清除该树枝下的所有分枝
		dmtn.removeAllChildren();
		//遍历路径下的所有文件和文件夹
		for(File f : file.listFiles())
		{
			if(!f.isDirectory() || !f.canWrite())   //如果为文件。则跳到下一轮循环
				continue; 
			//如果为文件夹则实例化一个分枝。并保存完整的路径信息、
			//完整路径由自定义的“Tag”类封装
			DefaultMutableTreeNode d = new DefaultMutableTreeNode(new Tag(f.getName(),f.getAbsoluteFile()));
			//判断该文件夹（f）下是否还含有子文件夹。如果还含有子文件夹。则给该新分枝（d）默认加一个空分枝。以便提醒用户该文件夹下还含有子文件夹。当用户展开该分枝时继续加载
			if(this.containerDirectory(f))   
				d.add(new DefaultMutableTreeNode());  
			//将新分枝添加到指定的树枝
			dmtn.add(d);
		}
	}

	//判断一个文件夹下面是否包含子文件夹
	public boolean containerDirectory(File file)
	{
		if(null == file || null == file.listFiles() || file.listFiles().length == 0)
			return false;
		//过滤后剩下来的为文件夹
		for(File f : file.listFiles())
		{
			if(f.isDirectory())
				return true;   //如果文件夹下包含子文件夹、则返回true
		}
		return false;
	}

	//自定义Tag类、、封装完整路径类
	private class Tag
	{
		private String name;   //文件夹名
		private File path;     //文件夹对应的File实例
		public Tag(){}
		public Tag(String name)
		{
			this.setName(name);
		}
		public Tag(String name,File path)
		{
			this(name);
			this.setPath(path);
		}
		public void setName(String name)
		{
			this.name = name;
		}
		public void setPath(File path)
		{
			this.path = path;
		}
		public String getName()
		{
			return this.name;
		}
		public File getPath()
		{
			return this.path;
		}
		public String toString()
		{
			return this.name;
		}
	}

	//程序入口main函数
	public static void main(String[] args)
	{
		new ResourceManage();
	}
}

